using System;
using System.Collections.Generic;
using System.Text;

namespace csammisrun.MsnLib.Utility
{
  public delegate void CommandHandler(CommandProcessor processor, MsnCommand command);
  public delegate void CommandErrorHandler(CommandProcessor processor, Transaction trans, int error);
  public delegate void MessageHandler(CommandProcessor processor, Message message);

  class CommandRegistrar
  {
    private Dictionary<string, Dictionary<string, List<CommandHandler>>> _responsehandlers =
      new Dictionary<string, Dictionary<string, List<CommandHandler>>>();

    private Dictionary<string, List<CommandHandler>> _serverhandlers =
      new Dictionary<string, List<CommandHandler>>();

    private Dictionary<string, List<CommandErrorHandler>> _errorhandlers =
      new Dictionary<string, List<CommandErrorHandler>>();

    private Dictionary<string, List<MessageHandler>> _msghandlers =
      new Dictionary<string, List<MessageHandler>>();

    private Dictionary<string, int> _commandsneedingpayload =
      new Dictionary<string, int>();

    public List<MessageHandler> GetHandlersForMessage(string contenttype)
    {
      string key = contenttype.ToLower();
      if(_msghandlers.ContainsKey(key))
      {
        return _msghandlers[key];
      }

      return null;
    }

    public List<CommandHandler> GetHandlersForCommand(string cmd, string answer)
    {
      Dictionary<string, List<CommandHandler>> answers = null;

      if (cmd == null)
      {
        answers = _serverhandlers;
      }
      else if (_responsehandlers.ContainsKey(cmd))
      {
        answers = _responsehandlers[cmd];
      }

      if (answers != null && answers.ContainsKey(answer))
      {
        return answers[answer];
      }
      return new List<CommandHandler>();
    }

    /// <summary>
    /// Clears all handler tables
    /// </summary>
    public void Clear()
    {
      foreach (KeyValuePair<string, List<MessageHandler>> kvp in _msghandlers)
      {
        kvp.Value.Clear();
      }

      foreach (KeyValuePair<string, List<CommandErrorHandler>> kvp in _errorhandlers)
      {
        kvp.Value.Clear();
      }

      foreach (KeyValuePair<string, List<CommandHandler>> kvp in _serverhandlers)
      {
        kvp.Value.Clear();
      }

      foreach(KeyValuePair<string, Dictionary<string, List<CommandHandler>>> kvp in _responsehandlers)
      {
        foreach (KeyValuePair<string, List<CommandHandler>> kvp2 in kvp.Value)
        {
          kvp2.Value.Clear();
        }
        kvp.Value.Clear();
      }

      _commandsneedingpayload.Clear();
    }

    /// <summary>
    /// Register a handler for a server response to a client request
    /// </summary>
    public void RegisterHandlerForServerResponse(string cmd, string answer, CommandHandler handler)
    {
      if (handler == null)
      {
        return;
      }

      if (!_responsehandlers.ContainsKey(cmd))
      {
        _responsehandlers[cmd] = new Dictionary<string, List<CommandHandler>>();
      }
      if (!_responsehandlers[cmd].ContainsKey(answer))
      {
        _responsehandlers[cmd][answer] = new List<CommandHandler>();
      }

      _responsehandlers[cmd][answer].Add(handler);
    }

    /// <summary>
    /// Register a handler for a packet sent by the server
    /// </summary>
    public void RegisterHandlerForServerCommand(string cmd, CommandHandler handler)
    {
      if (handler == null)
      {
        return;
      }

      if (!_serverhandlers.ContainsKey(cmd))
      {
        _serverhandlers[cmd] = new List<CommandHandler>();
      }
      _serverhandlers[cmd].Add(handler);
    }

    /// <summary>
    /// Register a handler for an error response from the server
    /// </summary>
    public void RegisterHandlerForError(string cmd, CommandErrorHandler handler)
    {
      if (handler == null)
      {
        return;
      }

      if (!_errorhandlers.ContainsKey(cmd))
      {
        _errorhandlers[cmd] = new List<CommandErrorHandler>();
      }
      _errorhandlers[cmd].Add(handler);
    }

    /// <summary>
    /// Register a handler for a specific message type
    /// </summary>
    public void RegisterHandlerForMessage(string contenttype, MessageHandler handler)
    {
      if (handler == null)
      {
        return;
      }

      string key = contenttype.ToLower();
      if (!_msghandlers.ContainsKey(key))
      {
        _msghandlers[key] = new List<MessageHandler>();
      }
      _msghandlers[key].Add(handler);
    }
  }
}
